import cv2
import numpy as np


def center_window(window_name, width, height):
    """ 将窗口移动到屏幕中心 """
    screen_width = 1920  # 根据实际情况设置屏幕宽度
    screen_height = 1080  # 根据实际情况设置屏幕高度
    x_pos = (screen_width - width) // 2
    y_pos = (screen_height - height) // 2
    cv2.moveWindow(window_name, x_pos, y_pos)


def process_meter_image(image):
    # 应用双边滤波
    bilateral_filtered = cv2.bilateralFilter(image, d=9, sigmaColor=75, sigmaSpace=75)

    # 转换为灰度图像
    gray_image = cv2.cvtColor(bilateral_filtered, cv2.COLOR_BGR2GRAY)

    # 使用高斯模糊去除噪声，防止干扰边缘检测
    blurred_image = cv2.GaussianBlur(gray_image, (7, 7), 0)

    # # 获取灰度图像的平均像素值
    # mean_value = cv2.mean(gray_image)[0]  # 取第一个值，即均值
    #
    # # 计算阈值，使用均值的1/3
    # threshold_value = mean_value / 3
    #
    # # 二值化处理
    # _, binary_image = cv2.threshold(gray_image, threshold_value, 255, cv2.THRESH_BINARY)

    # 二值化处理
    # 假设 gray_image 是已定义的灰度图像
    # 自适应二值化处理
    binary_image = cv2.adaptiveThreshold(
        blurred_image,  # 输入的灰度图
        255,  # 最大值，二值化后像素值上限
        cv2.ADAPTIVE_THRESH_MEAN_C,  # 自适应方法：局部均值
        cv2.THRESH_BINARY,  # 二值化类型
        399,  # 邻域大小（奇数）
        10  # 常数C，用于调节阈值
    )

    kernel = np.ones((9, 9), np.uint8)  # 设置kenenel大小
    erosion_1 = cv2.morphologyEx(binary_image, cv2.MORPH_OPEN, kernel)  # 开运算

    # # 定义 kernel，并应用腐蚀操作
    # kernel = np.ones((1, 1), np.uint8)  # 设置 kernel 为 5x5 大小
    # erosion_1 = cv2.erode(erosion_1, kernel, iterations=1)  # iterations 改为 5

    # 显示自适应二值化后的图像
    # cv2.imshow("binary_image", erosion_1)
    # cv2.waitKey(0)
    # cv2.destroyAllWindows()

    # 使用高斯模糊去除噪声，防止干扰边缘检测
    blurred_image = cv2.GaussianBlur(erosion_1, (7, 7), 0)

    # 使用Canny边缘检测
    edges = cv2.Canny(blurred_image, 10, 100)

    # 查找轮廓
    contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    if not contours:  # 检查是否找到轮廓
        print("未找到轮廓")
        return None, image  # 返回None和原始图像

    longest_contour = max(contours, key=lambda cnt: cv2.arcLength(cnt, True))  # 传入True表示闭合

    # 根据最大轮廓裁剪边缘图像
    x, y, w, h = cv2.boundingRect(longest_contour)
    cropped_image = image[y:y + h, x:x + w].copy()
    cropped_edges = edges[y:y + h, x:x + w].copy()

    # x, y = 0, 0
    # w, h = image.shape[:2]
    # cropped_image = image.copy()

    # 将边缘检测结果的非零像素（边缘）绘制为白色
    image[edges != 0] = [255, 255, 255]  # 白色

    # 使用Hough变换检测直线
    lines = cv2.HoughLinesP(edges[y:y + h, x:x + w], 1, np.pi / 180, threshold=50, minLineLength=30, maxLineGap=10)

    # 如果检测到直线
    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line[0]  # 获取每条直线的起始点和结束点
            # 绘制直线：在原图上绘制
            cv2.line(image, (x + x1, y + y1), (x + x2, y + y2), (0, 255, 0), 2)  # 绿色，线宽2

    # 找到最靠近中心的直线
    closest_line = None
    closest_distance = float('inf')
    second_closest_line = None
    second_closest_distance = float('inf')

    image_center_x = cropped_image.shape[1] // 2
    image_center_y = cropped_image.shape[0] // 2

    if lines is not None:
        for line in lines:
            x1, y1, x2, y2 = line[0]
            # 计算直线中点
            line_center_x = (x1 + x2) // 2
            line_center_y = (y1 + y2) // 2
            # 计算中点与图像中心的距离
            distance = ((line_center_x - image_center_x) ** 2 + (line_center_y - image_center_y) ** 2) ** 0.5

            # 计算直线的角度
            delta_y = y2 - y1
            delta_x = x2 - x1
            angle_rad = np.arctan2(delta_y, delta_x)  # 计算弧度
            angle_deg = np.degrees(angle_rad)  # 转换为度

            # 判断角度是否在范围内
            if -50 <= angle_deg <= 100:
                if distance < closest_distance:
                    closest_distance = distance
                    closest_line = (x1, y1, x2, y2)
            else:
                if distance < second_closest_distance:
                    second_closest_distance = distance
                    second_closest_line = (x1, y1, x2, y2)

    # 优先选择符合角度条件的直线
    final_line = closest_line if closest_line is not None else second_closest_line

    # 打印角度和绘制靠近中心的直线
    Angle_deg = 0
    if final_line is not None:
        x1, y1, x2, y2 = final_line
        cv2.line(cropped_image, (x1, y1), (x2, y2), (0, 0, 255), 2)  # 绘制最靠近中心的直线

        # 计算直线的角度
        delta_y = y2 - y1
        delta_x = x2 - x1
        Angle_deg = np.degrees(np.arctan2(delta_y, delta_x))  # 转换为度

    # 假设 Angle_deg 是你计算出的角度
    StartValue = -10
    OvertValue = 120
    OutValue = 12
    if StartValue <= Angle_deg <= OvertValue:
        mapped_value = (Angle_deg / OvertValue) * OutValue
        # 在图像上绘制角度值和映射后的值
        cv2.putText(cropped_image, f"Angle: {Angle_deg:.2f}", (10, 30), cv2.FONT_HERSHEY_SIMPLEX, 1, (255, 255, 255), 2)
    else:
        print("角度不在0到90范围内")

    return Angle_deg, cropped_image


# 示例调用
if __name__ == "__main__":
    image = cv2.imread(r"D:\Users\Administrator\Desktop\VoltWatcher_python\test_image\Meter4.png")
    angle_deg, result_image = process_meter_image(image)
    if angle_deg is not None:
        print(f"识别的角度: {angle_deg:.2f}度")
        cv2.imshow('Processed Image', result_image)  # 显示处理后的图像
        cv2.waitKey(0)
    cv2.destroyAllWindows()
